package com.googlecode.yami;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.swing.Box;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.table.DefaultTableColumnModel;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;

public class DbTable extends JComponent {

    private JTable dbTable;
    private Integer maxColWidth = 0;
    private JScrollPane jsp;
    private JPopupMenu popup;
    private DefaultTableModel model;
    final JMenuItem copy;
    final JMenuItem paste;
    final JMenuItem view;
    //final JMenuItem copyA;
    //final JMenuItem pasteA;

    // matrix to hold the type of each field
    private String[] typeField;

    // selected entry in the table (x, y)
    private String selection;
    private int selectionX;
    private int selectionY;
    private boolean selected = false;

    DbTable() {

	/*
	 * creating custom column model:
	 * 
	 * when it fills the table columns with the column names (see down in
	 * fillTableCols), setting the variable maxColWidth to the longest name,
	 * and finally here adding some pixel to it
	 */

	model = new DefaultTableModel();

	TableColumnModel cm = new DefaultTableColumnModel() {
	    public void addColumn(TableColumn tc) {
		tc.setMinWidth(maxColWidth * 8);
		tc.setMaxWidth(maxColWidth * 8);
		super.addColumn(tc);
	    }
	};

	// creating and setting the new table model, column model
	model = new DefaultTableModel();
	dbTable = new JTable(model);
	dbTable.setColumnModel(cm);

	/*
	 * setting the main layout for the table, and adding it to the scroll
	 * pane
	 */
	dbTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
	setLayout(new BorderLayout());
	jsp = new JScrollPane(dbTable);
	add(jsp, BorderLayout.CENTER);

	// create the popup menu for showing option for given field
	popup = new JPopupMenu();

	// create popup menu inside "Advanced View"
	//popupAdvanced = new JPopupMenu();

	// fill the popups
	copy = new JMenuItem("Copy");
	paste = new JMenuItem("Paste");
	view = new JMenuItem("Advanced View");

	//copyA = new JMenuItem("Copy");
	//pasteA = new JMenuItem("Paste");

	popup.add(copy);
	popup.add(paste);
	popup.add(view);

	//popupAdvanced.add(copyA);
	//popupAdvanced.add(pasteA);

	// popupmenu's listener
	ActionListener popuplistener = new ActionListener() {
	    @SuppressWarnings("deprecation")
	    public void actionPerformed(ActionEvent e) {
		if (selected) {
		    Object trigger = e.getSource();
		    if ((JMenuItem) trigger == copy) {
			MainWindow.clipboard.setClipboardContents(selection);
		    } else if ((JMenuItem) trigger == paste) {
			dbTable.setValueAt(MainWindow.clipboard.getClipboardContents(), selectionX, selectionY);
		    } else {

			// creat the main frame
			JFrame advanced = new JFrame();
			advanced.setTitle("Advanced view");
			advanced.setSize(400, 100);
			advanced.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

			// value label
			JLabel valuelbl = new JLabel("Value");
			valuelbl.setAlignmentY(Component.TOP_ALIGNMENT);

			// textarea containing the result
			final JTextArea valueArea = new JTextArea(selection);
			JScrollPane jspv = new JScrollPane(valueArea);
			jspv.setAlignmentY(Component.TOP_ALIGNMENT);

			// type
			JLabel typelbl = new JLabel("Type");
			// type value
			JLabel typelblV = new JLabel(typeField[selectionY]);

			// Boxes containing the components
			Box topBar = Box.createHorizontalBox();
			topBar.add(valuelbl);
			topBar.add(Box.createHorizontalStrut(10));
			topBar.add(jspv);

			Box bottomBar = Box.createHorizontalBox();
			bottomBar.add(typelbl);
			bottomBar.add(Box.createHorizontalStrut(15));
			bottomBar.add(typelblV);

			advanced.add(topBar);
			advanced.add(bottomBar, BorderLayout.SOUTH);

			advanced.show();

			/* Planned sub menu for textarea too
			 * ActionListener advancedPopuplistener = new ActionListener() {
			    public void actionPerformed(ActionEvent e) {
				Object trigger = e.getSource();
				if ((JMenuItem) trigger == copyA)
				    MainWindow.clipboard.setClipboardContents(valueArea.getSelectedText());
				else if ((JMenuItem) trigger == pasteA)
				    valueArea.insert(MainWindow.clipboard.getClipboardContents(), valueArea.getCaretPosition());
			    }
			};
			
			copyA.addActionListener(advancedPopuplistener);
			pasteA.addActionListener(advancedPopuplistener);

			// mouse listener for
			MouseListener avMl = new MouseListener() {

			    public void mouseClicked(MouseEvent e) {
				popupAdvanced.show(e.getComponent(), e.getX(), e.getY());
			    }

			    public void mouseEntered(MouseEvent e) {

			    }

			    public void mouseExited(MouseEvent e) {

			    }

			    public void mousePressed(MouseEvent e) {

			    }

			    public void mouseReleased(MouseEvent e) {
			    }

			};

			valueArea.addMouseListener(avMl);*/
		    }
		}
	    }
	};

	copy.addActionListener(popuplistener);
	paste.addActionListener(popuplistener);
	view.addActionListener(popuplistener);

	// listener connected to dbTable
	MouseListener ml = new MouseListener() {

	    JTable current;

	    public void mouseClicked(MouseEvent e) {

		// make sure that an entry is selected
		if (e.getButton() == 1)
		    selected = true;

		if (selected & e.getButton() == 3) {
		    current = (JTable) e.getSource();
		    selectionX = current.getSelectedRow();
		    selectionY = current.getSelectedColumn();
		    selection = (String) dbTable.getValueAt(selectionX, selectionY);
		    selected = true;
		    popup.show(e.getComponent(), e.getX(), e.getY());
		}
	    }

	    public void mouseEntered(MouseEvent e) {

	    }

	    public void mouseExited(MouseEvent e) {

	    }

	    public void mousePressed(MouseEvent e) {

	    }

	    public void mouseReleased(MouseEvent e) {
	    }

	};

	dbTable.addMouseListener(ml);

    }

    String[] fillTableCols(final Connection conn, final String tableName) {

	/*
	 * filling table columns:
	 * 
	 * in the query we are retrieving the column name for the actual
	 * database, by selecting from information_schema database the COLUMNS
	 * column, the result set is containing the column names for the actual
	 * database
	 */

	maxColWidth = 0;
	model.setColumnCount(0);
	model.setRowCount(0);
	Integer colNumb = 0;
	ResultSet colInTable;

	colInTable = Connect.execSQL(conn, "SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_NAME = \"" + tableName + "\"");
	try {
	    while (colInTable.next()) {
		String colName = colInTable.getString("COLUMN_NAME");
		if (colName.length() > maxColWidth) {
		    maxColWidth = colName.length();
		}
		model.addColumn(colName);
		colNumb++;
	    }
	} catch (Exception e) {
	}

	String[] cNs = new String[colNumb];

	colInTable = Connect.execSQL(conn, "SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_NAME = \"" + tableName + "\"");

	try {
	    int i = 0;
	    while (colInTable.next()) {
		String col = colInTable.getString("COLUMN_NAME");
		cNs[i] = col;
		i++;
	    }
	} catch (Exception e) {

	}

	return cNs;
    }

    void fillTableRows(final Connection conn, final String tableName, final String dbName, final String[] clName) {

	/*
	 * filling out the table columns:
	 * 
	 * the column name array is passed from the previous function. from
	 * informations_schema we are grabbing out the number of rows in the
	 * actual table. after we fill out the table with empty rows, then
	 * adding the values to x,y position.
	 */

	Integer rowNumb = 0;
	ResultSet rowContent;
	String[] emptyRow = null;
	Integer rowIndex = 0;
	ResultSet rowsInTable;

	rowsInTable = Connect.execSQL(conn, "SELECT TABLE_ROWS FROM information_schema.TABLES WHERE TABLE_NAME = \"" + tableName + "\"");
	try {
	    while (rowsInTable.next()) {
		rowNumb = rowsInTable.getInt("TABLE_ROWS");
	    }
	} catch (Exception e) {
	}

	for (int i = 0; i < rowNumb; i++) {
	    model.addRow(emptyRow);
	}

	// initialize the table for types
	typeField = new String[clName.length];

	for (int clIndex = 0; clIndex < clName.length; clIndex++) {
	    rowContent = Connect.execSQL(conn, "SELECT `" + clName[clIndex] + "` FROM `" + dbName + "`.`" + tableName + "`;");

	    if (rowContent != null) {
		try {
		    typeField[clIndex] = rowContent.getMetaData().getColumnTypeName(1);
		} catch (SQLException e1) {
		    e1.printStackTrace();
		}

		try {
		    while (rowContent.next()) {
			String rc = rowContent.getString(clName[clIndex]);
			if (rowIndex < rowNumb) {
			    model.setValueAt(rc, rowIndex, clIndex);
			}
			rowIndex++;
		    }
		    rowIndex = 0;
		} catch (Exception e) {
		    e.printStackTrace();
		}
	    }
	}
    }

}
